import { Component, ExoticComponent } from 'react'
import { Redirect, Route } from 'react-router-dom'

import Layout from '@/commponents/Layout'
import NotFound from '@/pages/ErrorPages/NotFound'

import store from '@/utils/storageManage'

import { IProps } from '@/types/routes'

// 能写的props都要写上，这样在别人改动前面的route文件时就必须按照你规划好的参数来传而不是随便乱传导致报错
export default class RouteGuard extends Component<IProps> {
  /**
   * 简单地判断当前token是否合法有效
   */
  checkAuth() {
    console.log('检查token是否存在', store.get('token'))
    return store.get('token')
  }

  /**
   * 最终的组件渲染
   * @param {*} path
   * @param {*} component
   * @returns
   */
  renderComponent(path: string, component: ExoticComponent, unBagUp?: boolean) {
    // 是否需要包裹？true为不需要，false为需要
    return unBagUp ? (
      <Route path={path} component={component} />
    ) : (
      <Layout>
        <Route path={path} component={component} />
      </Layout>
    )
  }
  render() {
    const { Routes, location } = this.props

    // 因为子模块index负责解析细分路由，所以这里只校验第一位，如果路由表管理所有路由，这行代码就不需要了
    let pathname = location.pathname.match(/\/(\w*)/)[0]

    // 因为首页pathname有可能是空，为了正确匹配，这里需要将路径替换为/home
    if (pathname === '/') {
      return <Redirect to="/home" />
    }

    // 首先从路由表中取出当前地址所对应的路由对象
    const targetRouter = Routes.find(router => {
      // console.log('路由表中取到的路径: %s; 当前访问路径: %s', router.path.replace(/\s*/g, ''), pathname)
      return router.path.replace(/\s*/g, '') === pathname
    })

    // 未获取到路由对象的，判断这是一个非法路由，直接跳转到404页面
    if (!targetRouter) {
      return <Route path={location.pathname} component={NotFound} />
    }

    // 解构当前路由对象
    const { unAuth, unBagUp, component } = targetRouter

    // 先处理已经登陆的情况
    // 约定俗成的规则：已登陆用户不可进入注册页和登陆页
    if (this.checkAuth()) {
      if (pathname === '/login' || pathname === '/register') {
        // 跳转至首页
        return <Redirect to="/home" />
      }
      // 其它路由直接返回指定组件进行渲染
      return this.renderComponent(location.pathname, component, unBagUp)
    }

    // 排除已登陆的情况后再处理其它未登陆情况
    // 判断是否需要登陆，不需要登陆授权的页面直接渲染
    if (unAuth) {
      return this.renderComponent(location.pathname, component, unBagUp)
    }

    // 需要登陆的带上当前路径跳转到登陆
    return (
      <Redirect
        // redirect传参
        // push存在时，新增一条history，否则修改当前history为to指向的地址
        // 使用state比较方便，不需要去解析search
        to={{
          pathname: '/login',
          // search: `?origin=${location.pathname}`,
          state: {
            origin: location.pathname,
          },
        }}
      />
    )
  }
}
